package com.sky.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sky.constant.JwtClaimsConstant;
import com.sky.constant.MessageConstant;
import com.sky.dto.UserLoginDTO;
import com.sky.entity.User;
import com.sky.exception.LoginFailedException;
import com.sky.mapper.UserMapper;
import com.sky.properties.JwtProperties;
import com.sky.properties.WXProperties;
import com.sky.service.UserService;
import com.sky.utils.HttpClientUtil;
import com.sky.utils.JwtUtil;
import com.sky.vo.UserLoginVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;

@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private WXProperties wxProperties;

    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 微信登录
     * 1. 需要把code + appid + oppsecret 一并发送给微信的后台:https://api.weixin.qq.com/sns/jscode2session
     * 2. 发起请求后,如果登录成功,微信后台会返回openId
     * 2.1 判断是新老用户
     * 1. 根据openId去查询user表,能查到就是老用户了,获取出来用户的信息
     * 2. 如果查询不到,就是新用户,执行添加操作 ,把这个用户存入user表,并获取主键返回
     * 2.2 构建token,token里面就方法用户id即可
     * 2.3 构建UserLoginVO对象: 组装用户的id,组装openId,组装token
     *
     * @param dto
     * @return
     */
    @Override
    public UserLoginVO login(UserLoginDTO dto) {
        // 发请求给微信后台
        // String url =wxProperties.getUrl();

        String openid = getOpenId(dto);
        // 判定是否登录成功
        if (openid == null) {
            throw new LoginFailedException(MessageConstant.LOGIN_FAILED);
        }
        // 判断是新老用户

        // 根据openid 去查询用户表,得到用户对象
        User user = userMapper.findById(openid);

        // 判断用户对象是否为null
        if (user == null) {
            // 新用户就添加操作
            user = User.builder().openid(openid).createTime(LocalDateTime.now()).build();
            userMapper.add(user);
        }

        // 组装数据,返回给Controller

        // 构建token  只需要把用户id放进去就可,方便后续任何操作都可以把id传递过来
        Map<String, Object> claims = new HashMap<>();
        claims.put(JwtClaimsConstant.USER_ID, user.getId());
        String token = JwtUtil.createJWT(jwtProperties.getUserSecretKey(), jwtProperties.getUserTtl(), claims);

        // 返回结果
        return UserLoginVO.builder().id(user.getId()).token(token).openid(openid).build();
    }

    /**
     * 发请求给微信后台,获取openid
     * @param dto
     * @return
     */
    public String getOpenId(UserLoginDTO dto) {
        // 封装数据
        Map<String, String> map = new HashMap<>();
        map.put("appid", wxProperties.getAppid()); // appid
        map.put("secret", wxProperties.getSecret());  // /密钥
        map.put("js_code", dto.getCode());  // 登录授权码,页面传递过的
        map.put("grant_type", wxProperties.getGrantType()); // 固定值authorization_code

        // 发请求
        String result = HttpClientUtil.doGet(wxProperties.getUrl(), map);
        System.out.println("result = " + result);

        //  解析结果,获取openid
        JSONObject jsonObject = JSON.parseObject(result);
        String openid = jsonObject.getString("openid");

        return openid;
    }
}
